package com.boom.common.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author:yzw
 * @Date:2021/3/25 下午9:00
 * @desc:
 * @version:1.0
 */
public class EncryptionUtils {

	private final static String BASE64HASH = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	private static boolean isMatcher(String str){
		//编译成一个正则表达式模式
		String reg = "([^\\u0000-\\u00ff])";
		Pattern pattern = Pattern.compile(reg);
		//匹配模式
		Matcher matcher = pattern.matcher(str);
		return matcher.matches();
	}

	/**
	 * 实现js window.btoa加密算法
	 * @param value
	 * @return java.lang.String
	 * @author yzw
	 * @time 2021/3/25 下午9:02
	 */
	public static String btoa(String value) {
		if(value==null||isMatcher(value)){
			throw new Error("INVALID_CHARACTER_ERR");
		}
		int i = 0,prev=0,ascii,mod=0;
		StringBuilder result = new StringBuilder();
		while (i<value.length()){
			ascii = value.charAt(i);
			mod = i%3;
			switch (mod){
				//第一个6位只需要让8位二进制右移两位
				case 0:
					result.append(BASE64HASH.charAt(ascii>>2));
					break;
				//第二个6位=第一个8位的后两位+第二个八位的前四位
				case 1:
					result.append(BASE64HASH.charAt((prev&3)<<4|(ascii>>4)));
					break;
				//第三个6位=第二个8位的后四位+第三个8位的前两位
				//第四个6位 = 第三个8位的后6位
				case 2:
					result.append(BASE64HASH.charAt((prev & 0x0f)<<2|(ascii>>6)));
					result.append(BASE64HASH.charAt(ascii&0x3f));
					break;
				default:
					break;
			}
			prev = ascii;
			i++;
		}
		//循环结束后看mod, 为0 证明需补3个6位，第一个为最后一个8位的最后两位后面补4个0。另外两个6位对应的是异常的“=”；
		// mod为1，证明还需补两个6位，一个是最后一个8位的后4位补两个0，另一个对应异常的“=”
		if(mod == 0){
			result.append(BASE64HASH.charAt((prev&3)<<4));
			result.append("==");
		}else if(mod == 1){
			result.append(BASE64HASH.charAt((prev&0x0f)<<2));
			result.append("=");
		}
		return result.toString();
	}

	/**
	 * 实现js window.atob解密算法
	 * @param inStr
	 * @return java.lang.String
	 * @author yzw
	 * @time 2021/3/25 下午9:10
	 */
	public static String atob(String inStr){
		if(inStr == null) {
			return null;
		}
		inStr = inStr.replaceAll("\\s|=", "");
		StringBuilder result = new StringBuilder();
		int cur;
		int prev=-1;
		int mod;
		int i=0;
		while (i < inStr.length()){
			cur = BASE64HASH.indexOf(inStr.charAt(i));
			mod = i % 4;
			switch (mod){
				case 1:
					result.append((char) (prev << 2 | cur >> 4));
					break;
				case 2:
					result.append((char) ((prev & 0x0f) << 4 | cur >> 2));
					break;
				case 3:
					result.append((char) ((prev & 3) << 6 | cur));
					break;
				default:
					break;
			}
			prev = cur;
			i++;
		}
		return result.toString();
	}
}
